package com.example.util;

import com.aliyun.openservices.shade.org.apache.commons.lang3.StringUtils;
import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Random;

/**
 */
@Slf4j
@Component
public class OSSClientUtil {

    private static OSSClient ossClient;
    //阿里云API的内或外网域名
    private static String ENDPOINT = "Const.ENDPOINT";
    //阿里云API的密钥Access Key ID
    private static String ACCESS_KEY_ID;
    //阿里云API的密钥Access Key Secret
    private static String ACCESS_KEY_SECRET;
    //阿里云API的bucket名称
    private static String BACKET_NAME;
    //阿里云API的文件夹名称
    private static String FOLDER = "Const.FILEDIR";

    @Value("${bucket_name}")
    private void setBucketName(String bucketName) {
        OSSClientUtil.BACKET_NAME = bucketName;
    }

    @Value("${oss_access_key_id}")
    private void setAccessKeyId(String accessKeyId) {
        OSSClientUtil.ACCESS_KEY_ID = accessKeyId;
    }

    @Value("${oss_access_key_secret}")
    private void setAccessKeySecret(String accessKeySecret) {
        OSSClientUtil.ACCESS_KEY_SECRET = accessKeySecret;
    }


    /**
     * 初始化
     */
    @PostConstruct
    public void init() {
        ClientConfiguration conf = new ClientConfiguration();
        conf.setMaxConnections(1000);
        conf.setConnectionTimeout(15 * 1000);
        conf.setSocketTimeout(15 * 1000);
        ossClient = new OSSClient(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET, conf);
    }

    /**
     * 销毁
     */
    public void destory() {
        ossClient.shutdown();
    }

    /**
     * 上传图片
     *
     * @param url
     */
    public String uploadImg2Oss(String url) {
        File fileOnServer = new File(url);
        FileInputStream fin;
        try {
            fin = new FileInputStream(fileOnServer);
            String[] split = url.split("/");
            this.uploadFile2OSS(fin, split[split.length - 1]);
        } catch (Exception e) {
            log.info("上传失败");
        }
        fileOnServer.delete();
        return getImgUrl(url);
    }


    public String uploadImg2Oss(MultipartFile file) throws Exception {
        if (file.getSize() > 1024 * 1024) {
            throw new Exception("上传图片大小不能超过1M！");
        }
        String originalFilename = file.getOriginalFilename();
        String substring = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
        Random random = new Random();
        String name = random.nextInt(10000) + System.currentTimeMillis() + substring;
        try {
            InputStream inputStream = file.getInputStream();
            this.uploadFile2OSS(inputStream, name);
            return name;
        } catch (Exception e) {
            throw new Exception("图片上传失败02");
        }
    }

    /**
     * 获得图片路径
     *
     * @param fileUrl
     * @return
     */
    public String getImgUrl(String fileUrl) {
        if (!StringUtils.isEmpty(fileUrl)) {
            String[] split = fileUrl.split("/");
            return this.getUrl(FOLDER + split[split.length - 1]);
        }
        return null;
    }

    /**
     * 上传到OSS服务器  如果同名文件会覆盖服务器上的
     *
     * @param instream 文件流
     * @param fileName 文件名称 包括后缀名
     * @return 出错返回"" ,唯一MD5数字签名
     */
    public String uploadFile2OSS(InputStream instream, String fileName) {
        String ret = "";
        try {
            //创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(instream.available());
            objectMetadata.setCacheControl("no-cache");
            objectMetadata.setHeader("Pragma", "no-cache");
            objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));
            objectMetadata.setContentDisposition("inline;filename=" + fileName);
            //上传文件
            PutObjectResult putResult = ossClient.putObject(BACKET_NAME, FOLDER + fileName, instream, objectMetadata);
            ret = getImgUrl(fileName);
//            ret = putResult.getETag();
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (instream != null) {
                    instream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return ret;
    }

    /**
     * Description: 判断OSS服务文件上传时文件的contentType
     *
     * @param FilenameExtension 文件后缀
     * @return String
     */
    public static String getcontentType(String FilenameExtension) {
        if (FilenameExtension.equalsIgnoreCase(".bmp")) {
            return "image/bmp";
        }
        if (FilenameExtension.equalsIgnoreCase(".gif")) {
            return "image/gif";
        }
        if (FilenameExtension.equalsIgnoreCase(".jpeg") ||
                FilenameExtension.equalsIgnoreCase(".jpg") ||
                FilenameExtension.equalsIgnoreCase(".png")) {
            return "image/jpeg";
        }
        if (FilenameExtension.equalsIgnoreCase(".html")) {
            return "text/html";
        }
        if (FilenameExtension.equalsIgnoreCase(".txt")) {
            return "text/plain";
        }
        if (FilenameExtension.equalsIgnoreCase(".vsd")) {
            return "application/vnd.visio";
        }
        if (FilenameExtension.equalsIgnoreCase(".pptx") ||
                FilenameExtension.equalsIgnoreCase(".ppt")) {
            return "application/vnd.ms-powerpoint";
        }
        if (FilenameExtension.equalsIgnoreCase(".docx") ||
                FilenameExtension.equalsIgnoreCase(".doc")) {
            return "application/msword";
        }
        if (FilenameExtension.equalsIgnoreCase(".xml")) {
            return "text/xml";
        }
        if (FilenameExtension.equalsIgnoreCase(".xls") ||
                FilenameExtension.equalsIgnoreCase(".xlsx")) {
            return "application/vnd.ms-excel";
        }
        if (FilenameExtension.equalsIgnoreCase(".pdf")) {
            return "application/pdf";
        }
        if (FilenameExtension.equalsIgnoreCase(".mp3")) {
            return "audio/mp3";
        }
        return "image/jpeg";
    }

    /**
     * 获得url链接
     *
     * @param key
     * @return
     */
    public String getUrl(String key) {
        // 设置URL过期时间为10年  3600l* 1000*24*365*10
        Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
        // 生成URL
        URL url = ossClient.generatePresignedUrl(BACKET_NAME, key, expiration);
        if (url != null) {
            String head = (url.toString().split("\\?")[0]).split(":")[1];
            String httpsUrl = "https:" + head;
            return httpsUrl;
        }
        return null;
    }

    /**
     * 上传网络流
     *
     * @param url
     * @param fileName
     * @return
     */
    public String uploadUrlFile(String url, String fileName) {
        String result = "";
        if ("/".equals(url.charAt(0))) {
            url = "https:" + url;
        }
        InputStream inputStream = null;
        try {
//            OSSClient ossClient = new OSSClient(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
            inputStream = new URL(url).openStream();
            ossClient.putObject(BACKET_NAME, FOLDER + fileName, inputStream);
            result = getImgUrl(fileName);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    //链接url下载图片
    public void downloadPicture(String urlList, String imageName) {
        URL url = null;
        int imageNumber = 0;
        try {
            url = new URL(urlList);
            DataInputStream dataInputStream = new DataInputStream(url.openStream());

            FileOutputStream fileOutputStream = new FileOutputStream(new File(imageName));
            ByteArrayOutputStream output = new ByteArrayOutputStream();

            byte[] buffer = new byte[1024];
            int length;

            while ((length = dataInputStream.read(buffer)) > 0) {
                output.write(buffer, 0, length);
            }
            byte[] context = output.toByteArray();
            fileOutputStream.write(output.toByteArray());
            dataInputStream.close();
            fileOutputStream.close();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 上传到OSS服务器  如果同名文件会覆盖服务器上的
     *
     * @param instream 文件流
     * @param fileName 文件名称 包括后缀名
     * @return 出错返回"" ,唯一MD5数字签名
     */
    public String uploadFile2OSS_2(InputStream instream, String fileName) {
        String ret = "";
        try {
            //创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(instream.available());
            objectMetadata.setCacheControl("no-cache");
            objectMetadata.setHeader("Pragma", "no-cache");
            objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));
            objectMetadata.setContentDisposition("inline;filename=" + fileName);
            //上传文件
            PutObjectResult putResult = ossClient.putObject(BACKET_NAME, FOLDER + fileName, instream, objectMetadata);
//            ret = putResult.getETag();
            ret = getImgUrl(fileName);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (instream != null) {
                    instream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return ret;
    }

    /**
     * 设置ContentDisposition 为 attachment：表示强制下载
     *
     * @param instream
     * @param fileName
     * @return
     */
    public String uploadFile2OSSDownload(InputStream instream, String fileName) {
        String ret = "";
        try {
            //创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(instream.available());
            objectMetadata.setCacheControl("no-cache");
            objectMetadata.setHeader("Pragma", "no-cache");
            objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));
            objectMetadata.setContentDisposition("attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
            //上传文件
            PutObjectResult putResult = ossClient.putObject(BACKET_NAME, FOLDER + fileName, instream, objectMetadata);
//            ret = putResult.getETag();
            ret = getImgUrl(fileName);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (instream != null) {
                    instream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return ret;
    }

    public void downloadFile(String fileName) {
        try {
            // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
            OSSObject ossObject = ossClient.getObject(BACKET_NAME, FOLDER + URLEncoder.encode(fileName, "utf-8"));

            // 读取文件内容。
            BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
            while (true) {
                String line = reader.readLine();
                if (line == null) break;
            }

            // 数据读取完成后，获取的流必须关闭，否则会造成连接泄漏，导致请求无连接可用，程序无法正常工作。
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }

//    public static void main(String[] args) throws FileNotFoundException {
//        ossClient = new OSSClient(ENDPOINT, "LTAId7c5UVsaDGx2", "yab2r4C7wX5IVmMLQYGBYVAxT9lzha");
//        BACKET_NAME = "dev-m-bucket";
//        OSSClientUtil ossClientUtil = new OSSClientUtil();
//        FileInputStream fileInputStream = new FileInputStream("C:\\Users\\meifute\\Desktop\\jenkins.png");
//        String s = ossClientUtil.uploadFile2OSS_2(fileInputStream, "89898.jpg");
//        System.out.println("------------");
//        System.out.println(s);
//
//    }
    }

    public InputStream downLoadImage(String fileName) {
        InputStream inputStream = null;
        try {
            // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
            OSSObject ossObject = ossClient.getObject(BACKET_NAME, FOLDER + URLEncoder.encode(fileName, "utf-8"));
            inputStream = ossObject.getObjectContent();
           /* File file = new File(System.currentTimeMillis() + ".pdf");
            file.createNewFile();*/
        } catch (Exception e) {
            e.printStackTrace();
        }

        return inputStream;
    }


    public String downLoadFile(String fileName) {
        InputStream inputStream = null;
        String result = "/tmp/" + System.currentTimeMillis() + ".pdf";
        try {
            // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
            OSSObject ossObject = ossClient.getObject(BACKET_NAME, FOLDER + URLEncoder.encode(fileName, "utf-8"));
            inputStream = ossObject.getObjectContent();
            BufferedInputStream bi = new BufferedInputStream(inputStream);
            FileOutputStream fos = new FileOutputStream(result);
            byte[] by = new byte[1024];
            int len = 0;
            while ((len = bi.read(by)) != -1) {
                fos.write(by, 0, len);
            }
            fos.close();
            bi.close();


            log.info("获取pdf转文件正常");
        } catch (Exception e) {
            e.printStackTrace();
            log.info("获取pdf转文件异常:{}", e);
        }
        return result;
    }

    public void removeFile(String fileName) throws UnsupportedEncodingException {
        String key = FOLDER + URLEncoder.encode(fileName, "utf-8");
        log.info("========================================:" + key);
        ossClient.deleteObject(BACKET_NAME, key);
    }

    /**
     * 上传到OSS服务器  如果同名文件会覆盖服务器上的
     *
     * @param instream 文件流
     * @param fileName 文件名称 包括后缀名
     * @return 出错返回"" ,唯一MD5数字签名
     */
    public String uploadExcelFile2OSS(InputStream instream, String fileName) {
        String ret = "";
        try {
            //创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(instream.available());
            objectMetadata.setCacheControl("no-cache");
            objectMetadata.setHeader("Pragma", "no-cache");
            objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));
            objectMetadata.setContentDisposition("inline;filename=" + fileName);
            //上传文件
            PutObjectResult putResult = ossClient.putObject(BACKET_NAME, FOLDER + fileName, instream, objectMetadata);
            ret = getExeclUrl(fileName);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (instream != null) {
                    instream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return ret;
    }


    /**
     * 获得execl文件路径
     *
     * @param fileUrl
     * @return
     */
    public String getExeclUrl(String fileUrl) {
        if (!StringUtils.isEmpty(fileUrl)) {
            String[] split = fileUrl.split("/");
            String key = FOLDER + split[split.length - 1];
            Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 7);
            // 生成URL
            URL url = ossClient.generatePresignedUrl(BACKET_NAME, key, expiration);
            if (url != null) {
                String head = (url.toString().split("\\?")[0]).split(":")[1];
                String httpsUrl = "https:" + head;
                return httpsUrl;
            }
        }
        return null;
    }

}
